import { Body, Controller, Get, Post, Request, Response } from "@nestjs/common";
import { FastifyReply, FastifyRequest } from "fastify";
import { WebResult } from "src/common/web.result";
import { HTTPRequestDTO } from "./dto/http-request.dto";

@Controller("tool")
export class ToolController {
  constructor() {}

  /**
   * @param request request
   * @param response response
   * @returns 返回 纯文本
   */
  @Get("/ip")
  getIP(
    @Request() request: FastifyRequest,
    @Response() response: FastifyReply,
  ) {
    response.header("content-type", "text/plain;charset=utf-8");
    if (!request.headers.host.includes(":4433")) {
      response.send("拒绝访问");
      return;
    }
    const ip = request.socket.remoteAddress;
    const port = request.socket.remotePort;
    response.send(`${ip}:${port}`);
  }

  @Get("/x-real-ip")
  getXRealIP(@Request() request: FastifyRequest) {
    const ip = request.headers["x-real-ip"];
    return WebResult.success(ip);
  }

  @Get("/x-forwarded-for")
  getXForwardedFor(@Request() request: FastifyRequest) {
    const ip = request.headers["x-forwarded-for"];
    return WebResult.success(ip);
  }

  @Post(["/http", "/http-request"])
  async httpRequest(@Body() requestDTO: HTTPRequestDTO) {
    let method = "GET";
    let headers = {};
    let body = undefined;

    // method
    if (requestDTO.method) method = requestDTO.method;
    // headers
    headers = Object.assign(
      requestDTO.headers ? requestDTO.headers : {},
      requestDTO.header ? requestDTO.header : {},
    );
    // body
    if (method === "GET" || method === "get") {
      body = undefined;
    } else if (
      headers["Content-Type"].includes("form") ||
      headers["content-type"].includes("form")
    ) {
      body = new FormData();
      const data = requestDTO.body || requestDTO.data || {};
      for (const k of Object.keys(data)) {
        body.append(k, data[k]);
      }
    } else {
      body = requestDTO.body || requestDTO.data || undefined;
    }

    try {
      const data = await fetch(requestDTO.url, {
        method,
        headers,
        body,
      }).then((response) => {
        const contentType = response.headers.get("content-type");
        if (contentType && contentType.includes("application/json")) {
          return response.json();
        }
        return response.text();
      });
      return WebResult.success(data);
    } catch (e) {
      console.error(e);
      e.stack = undefined;
      return WebResult.failure(e);
    }
  }
}
